package com.tygz.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auto.base.pojo.AccessToken;
import com.auto.base.pojo.Attach;
import com.auto.base.pojo.AttachExample;
import com.auto.base.pojo.AttachExample.Criteria;
import com.auto.base.pojo.City;
import com.auto.base.pojo.CityExample;
import com.auto.base.pojo.GeneralUser;
import com.auto.base.pojo.Post;
import com.auto.base.pojo.PostFocus;
import com.auto.base.pojo.UserWeixin;
import com.auto.base.service.AccessTokenService;
import com.auto.base.service.AttachService;
import com.auto.base.service.CityService;
import com.auto.base.service.GeneralUserService;
import com.auto.base.service.PostFocusService;
import com.auto.base.service.PostService;
import com.auto.base.service.UserWeixinService;
import com.auto.util.SystemUtil;
import com.base.cache.memcache.CommonMemcached;
import com.base.common.CommonConstants;
import com.base.model.interfaze.MapperCallBackAdapter;
import com.base.util.JUtil;
import com.base.util.Page;
import com.tygz.pojo.cache.LoginCache;
import com.tygz.service.ApiUserService;
import com.weixin.open.WeixinApi;

@Transactional
@Service
public class ApiUserServiceImpl implements ApiUserService {

	private final Logger log = LoggerFactory.getLogger(ApiUserServiceImpl.class);
	private final static String namespace = "com.ajw.service.impl.ApiUserServiceImpl"; 
	@Resource private GeneralUserService generalUserService;
	@Resource private AccessTokenService accessTokenService;
	@Resource private AttachService attachService;
	@Resource private CommonMemcached commonMemcached;
	@Resource private PostService postService;
	@Resource private PostFocusService postFocusService;
	@Resource private UserWeixinService userWeixinService;
	@Resource private CityService cityService;

	public GeneralUser getUserById(int userId) throws Exception {
		String userKey = JUtil.getCacheKey(namespace,"generalUser",userId);
		GeneralUser userCache = commonMemcached.get(userKey);
		if(null!=userCache){
			return userCache;
		}
		return getUserByIdNotByCache(userId);
	}



	@Override
	public void login(Map<String, Object> map, GeneralUser user) throws Exception {

		GeneralUser tmp = null;
		String key = JUtil.getCacheKey(namespace,"access",user.getTelphone());
		LoginCache loginCache = commonMemcached.get(key);
		if(!JUtil.isNULL(loginCache)){

			//从缓存里面获取用户信息
			String userKey = JUtil.getCacheKey(namespace,"generalUser",loginCache.getUserId());
			GeneralUser generalUserCache = this.commonMemcached.get(userKey);
			if(JUtil.isNULL(generalUserCache)){
				//需要从数据库重新查询
				tmp = new GeneralUser();
				tmp.setId(loginCache.getUserId());
				tmp.setEnabled(CommonConstants.ENABLE);
				tmp = this.generalUserService.findGeneralUser(tmp, null);
				if(JUtil.isNULL(tmp)){
					//没有查询到
					loginNotByCache(map,user);
					return;
				}else{
					generalUserCache = tmp;
					tmp = null;
				}
			}
			//缓存存在
			String password = generalUserCache.getPassword(),nowPwd = (user.getPassword());
			if(!password.equalsIgnoreCase(nowPwd)){
				throw new RuntimeException("该手机号码或者密码错误");
			}
			String accessToken = loginCache.getAccessToken();
			if(JUtil.checkExpired(loginCache.getExpiredTime())){
				//已经过期我们需要重新生成
				accessToken = JUtil.uuid();
				AccessToken qat = new AccessToken();
				qat.setAccessToken(accessToken);
				qat.setUserId(generalUserCache.getId());
				qat.setExpiredTime(JUtil.getExpiredTime());
				this.accessTokenService.modifyAccessTokenByPkSelective(qat);
				//重新加入缓存
				loginCache.setAccessToken(accessToken);
				loginCache.setExpiredTime(qat.getExpiredTime());
				this.commonMemcached.set(key, CommonConstants.CACHEEXPIREDTIME, loginCache);
			}

			//表示已经登陆成功了
			long nowTime = new Date().getTime();
			generalUserCache.setId(loginCache.getUserId());
			//generalUserCache.setLastLat(generalUserCache.getLat());
			//generalUserCache.setLastLon(generalUserCache.getLon());
			generalUserCache.setLastLoginTime(generalUserCache.getLoginTime());
			generalUserCache.setLoginTime(nowTime);
			if(null!=user.getLng()){
				generalUserCache.setLng(user.getLng());
			}
			if(null!=user.getLat()){
				generalUserCache.setLat(user.getLat());
			}


			generalUserCache.setTelphone(user.getTelphone());

			this.generalUserService.modifyGeneralUserByPkSelective(generalUserCache);

			this.commonMemcached.set(userKey, CommonConstants.CACHEEXPIREDTIME, generalUserCache);

			map.put("accessToken", accessToken);
			//generalUserCache.setId(null);
			map.put("userInfo", generalUserCache);
		}else{
			loginNotByCache(map,user);
		}
	}


	public GeneralUser getUserByIdNotByCache(int userId,String userKey) throws Exception {

		GeneralUser tmp = new GeneralUser();
		tmp.setEnabled(CommonConstants.ENABLE);
		tmp.setId(userId);
		tmp = this.generalUserService.findGeneralUser(tmp, null);
		Assert.notNull(tmp, "获取用户数据失败");
		//加入到缓存
		this.commonMemcached.set(userKey, CommonConstants.CACHEEXPIREDTIME, tmp);
		return tmp;

	}


	public GeneralUser getUserByIdNotByCache(int userId) throws Exception {

		GeneralUser tmp = new GeneralUser();
		tmp.setEnabled(CommonConstants.ENABLE);
		tmp.setId(userId);
		tmp = this.generalUserService.findGeneralUser(tmp, null);
		Assert.notNull(tmp, "获取用户数据失败");
		//加入到缓存
		if(null == tmp.getImgName()){
			//从微信端取数据
			UserWeixin uw = new UserWeixin();
			uw.setUid(userId);
			uw.setEnabled(CommonConstants.ENABLE);
			uw = this.userWeixinService.findUserWeixin(uw, null);
			if(null!=uw){
			  tmp.setUserIcon(uw.getHeadUrl());	
			}
		}
		String userKey = JUtil.getCacheKey(namespace,"generalUser",tmp.getTelphone());
		this.commonMemcached.set(userKey, CommonConstants.CACHEEXPIREDTIME, tmp);
		return tmp;

	}



	private void loginNotByCache(Map<String, Object> map,GeneralUser user) throws Exception{
		GeneralUser tmp = new GeneralUser();
		tmp.setTelphone(user.getTelphone());
		tmp.setEnabled(CommonConstants.ENABLE);
		tmp = this.generalUserService.findGeneralUser(tmp,null);
		if (JUtil.isNULL(tmp)){
			throw new RuntimeException("该手机号码不存在系统!");
		}

		String pwd = tmp.getPassword(),nowPwd = (user.getPassword());

		if(!JUtil.isNull(pwd) && pwd.equalsIgnoreCase(nowPwd)){
			//表示已经登陆成功了
			long nowTime = new Date().getTime();
			user.setId(tmp.getId());
			user.setLoginTime(nowTime);
			user.setLastLoginTime(tmp.getLoginTime());

			tmp.setLoginTime(nowTime);
			tmp.setLastLoginTime(user.getLastLoginTime());
			if(null!=user.getLng()){
				tmp.setLng(user.getLng());

			}
			if(null!=user.getLat()){
				tmp.setLat(user.getLat());
			}



			this.generalUserService.modifyGeneralUserByPkSelective(user);
			user = null;

			AccessToken qat = new AccessToken();
			qat.setUserId(tmp.getId());
			AccessToken at = this.accessTokenService.findAccessToken(qat, null);
			String accessToken = null;
			if(JUtil.isNULL(at)){
				//重新插入
				accessToken = JUtil.uuid();
				AccessToken ak = reCreateAccess(tmp.getId(),accessToken);
				String key = JUtil.getCacheKey(namespace,"access",tmp.getTelphone());
				LoginCache loginCache = new LoginCache();
				loginCache.setAccessToken(accessToken);
				loginCache.setExpiredTime(ak.getExpiredTime());
				loginCache.setPassword(tmp.getPassword());
				loginCache.setUserId(tmp.getId());
				this.commonMemcached.set(key, CommonConstants.CACHEEXPIREDTIME, loginCache);
			}else if((!JUtil.isNULL(at) && !JUtil.checkExpired(at.getExpiredTime()))){
				//过期
				at.setExpiredTime(JUtil.getExpiredTime());
				accessToken = JUtil.uuid();
				at.setAccessToken(accessToken);
				this.accessTokenService.modifyAccessTokenByPkSelective(at);
				String key = JUtil.getCacheKey(namespace,"access",tmp.getTelphone());
				LoginCache loginCache = new LoginCache();
				loginCache.setAccessToken(accessToken);
				loginCache.setExpiredTime(at.getExpiredTime());
				loginCache.setPassword(tmp.getPassword());
				loginCache.setUserId(tmp.getId());
				this.commonMemcached.set(key, CommonConstants.CACHEEXPIREDTIME, loginCache);
			}else{
				accessToken = at.getAccessToken();
			}
			String userKey = JUtil.getCacheKey(namespace,"generalUser",tmp.getId());
			this.commonMemcached.set(userKey, CommonConstants.CACHEEXPIREDTIME, tmp);
			map.put("accessToken", accessToken);
			//tmp.setId(null);
			map.put("userInfo", tmp);
			return;
		}else{
			throw new RuntimeException("密码错误");
		}
	}

	private AccessToken reCreateAccess(int userId,String accessToken) throws Exception{
		AccessToken qat = new AccessToken();
		qat.setAccessToken(accessToken);
		qat.setUserId(userId);
		qat.setExpiredTime(JUtil.getExpiredTime());
		this.accessTokenService.insertAccessToken(qat);
		return qat;
	}


	@Override
	public void addCache(Map<String, Object> map, GeneralUser tmp)
			throws Exception {
		// TODO Auto-generated method stub
		this.generalUserService.modifyGeneralUserByPkSelective(tmp);

		String accessToken = null;
		//重新插入
		accessToken = JUtil.uuid();
		AccessToken ak = reCreateAccess(tmp.getId(),accessToken);
		String key = JUtil.getCacheKey(namespace,"access",tmp.getTelphone());
		LoginCache loginCache = new LoginCache();
		loginCache.setAccessToken(accessToken);
		loginCache.setExpiredTime(ak.getExpiredTime());
		loginCache.setPassword(tmp.getPassword());
		loginCache.setUserId(tmp.getId());
		this.commonMemcached.set(key, CommonConstants.CACHEEXPIREDTIME, loginCache);
		String userKey = JUtil.getCacheKey(namespace,"generalUser",tmp.getId());
		this.commonMemcached.set(userKey, CommonConstants.CACHEEXPIREDTIME, tmp);
		map.put("accessToken", accessToken);
		map.put("userInfo", tmp);
	}


	private void checkUser(GeneralUser user) throws Exception{
		Assert.notNull(user.getId(), "用户ID不能为空！");
		if(null!=user.getTelphone() || null!=user.getPassword()){
			throw new IllegalArgumentException("用户不能修改其电话号码或者密码！");
		}
		//if(user.getAge() == null && user.getBirth() == null && user.getCity() && user.getCompany() && user.getDest() && user.getIntro() && user.getLat() && user.getLng() && user.getLocationCity() && user.getNickName() && user.getSex() && user.get)
		GeneralUser query = new GeneralUser();
		query.setEnabled(CommonConstants.ENABLE);
		query.setId(user.getId());
		int flag = this.generalUserService.countGeneralUser(query);
		if(flag <=0){
			throw new IllegalArgumentException("此ID对应无效用户信息!");
		}

	}

	/**
	 * 用户信息的修改
	 */
	@Override
	public GeneralUser updateUserInfo(final GeneralUser user) throws Exception {

		checkUser(user);
		if(null!=user.getHeadId()){
			Attach tmp = new Attach();
			//将用户原头像解绑
			tmp.setItemType(CommonConstants.IMGTYPE);//表示头像
			tmp.setEnabled(CommonConstants.ENABLE);
			tmp.setId(user.getHeadId());

			Attach tmpQ = new Attach();
			//tmpQ.setItemType(CommonConstants.IMGTYPE);//表示头像
			tmpQ.setEnabled(1);
			//tmpQ.setId(user.getHeadId());
			//tmpQ.setItemId(user.getId());

			this.attachService.modifyAttach(tmpQ, new MapperCallBackAdapter(){
				@Override
				public void doCriteria(Object obj) throws Exception {
					AttachExample.Criteria c = (AttachExample.Criteria)obj;
					c.andItemTypeEqualTo(CommonConstants.IMGTYPE);
					c.andItemIdEqualTo(user.getId());
				}

			} );

			tmpQ = null;
			tmp.setItemType(CommonConstants.IMGTYPE);//表示头像
			tmp.setEnabled(CommonConstants.ENABLE);
			tmp.setId(user.getHeadId());
			Attach tmp1 = this.attachService.findAttach(tmp, null);
			Assert.notNull(tmp1, "根据headId查询附件信息失败 请先确认附件是否存在!");
			tmp.setItemId(user.getId());
			//将头像ID和用户绑定
			this.attachService.modifyAttachByPkSelective(tmp);
		}

		user.setEnabled(CommonConstants.ENABLE);
		this.generalUserService.modifyGeneralUserByPkSelective(user);
		GeneralUser query = new GeneralUser();
		query.setEnabled(CommonConstants.ENABLE);
		query.setId(user.getId());
		query = this.generalUserService.findGeneralUser(query, null);
		String userKey = JUtil.getCacheKey(namespace,"generalUser",user.getId());
		if(null!=query){
			//缓存失效
			this.commonMemcached.set(userKey,CommonConstants.CACHEEXPIREDTIME,query);
			return query;
		}else{
			//缓存失效
			this.commonMemcached.delete(userKey);
			throw new RuntimeException("更新后根据ID查询用户信息失败！");
		}

	}


	/**
	 * 发表帖子
	 */
	@Override
	public void doPush(Post post,final String fileIds) throws Exception {
		// TODO Auto-generated method stub

		if(null == fileIds || StringUtils.isEmpty(fileIds)){
			//throw new RuntimeException("附件字段为空！");
			this.postService.insertPost(post);
			return;
		}
		final List<Integer> list = JUtil.splitToListInteger(fileIds);
		//判断附件ID是否存在
		List<Attach> listAttach = this.attachService.listAttach(new Attach(), null, null, new MapperCallBackAdapter() {
			@Override
			public void doCriteria(Object obj) throws Exception {
				Criteria criteria = (Criteria)obj;
				criteria.andEnabledEqualTo(CommonConstants.ENABLE);
				criteria.andIdIn(list);
			}
		});
		if(null == listAttach || listAttach.isEmpty() || listAttach.size() < list.size()){
			throw new RuntimeException("有附件ID不存在系统中!");
		}

		for(Attach q:listAttach){
			if(q.getItemType() != CommonConstants.SELFTYPE){
				throw new RuntimeException("有附件类型不是帖子类型附件!");
			}
			if(!JUtil.isNULL(q.getItemId())){
				throw new RuntimeException("该附件已被使用，不属于你，你不能用!");
			}
		}


		int id = this.postService.insertPost(post);

		for(Integer aid:list){
			Attach tmp = new Attach();
			tmp.setUpdateTime(new Date().getTime());
			tmp.setItemId(id);
			tmp.setId(aid);
			tmp.setIsImage(0);
			this.attachService.modifyAttachByPkSelective(tmp);			
		}
	}

	/**
	 * 文件上传
	 */

	public JSONArray upload(MultipartFile[] uploadFiles,int type) throws Exception{
		List<String> limitImgList = JUtil.splitToListString(SystemUtil.getInstance().getParamMapValue("limit_img_list"));
		JSONArray list = new JSONArray();
		for(MultipartFile myfile:uploadFiles){
			if(myfile.isEmpty()){
				throw new RuntimeException("文件未上传!");
			}

			String oldFileName = myfile.getOriginalFilename(), suffix = JUtil.getFileSuffix(oldFileName);
			Attach tmp = new Attach();
			tmp.setIsImage(1);
			if(limitImgList.contains(suffix)){
				tmp.setIsImage(0);//是图片
			}

			String fileName =JUtil.getFileNameByParameters("yh-"+type,suffix);
			tmp.setFileName(fileName);
			String filePathPreffix = SystemUtil.getInstance().getParamMap().get("sys_file_save_dir");
			String realPath = filePathPreffix+"/"+type;
			tmp.setFileLocation(realPath);
			tmp.setAddTime(new Date().getTime());
			tmp.setItemType(type);
			File file = new File(realPath);
			if(!file.exists()){//地址不存在处理
				file.mkdirs();
			}
			FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath,fileName)); 
			int res = this.attachService.insertAttach(tmp);
			JSONObject obj = new JSONObject();
			obj.put("fileId", res);
			String url = SystemUtil.getInstance().getParamMapValue("sys_file_down_url_preffix")+"/"+type+"/"+fileName;
			obj.put("url", url);
			list.add(obj);
		}
		return list;
	}




	@Override
	public int doAgree(PostFocus postFocus) throws Exception {
		Post post = new Post();
		post.setEnabled(CommonConstants.ENABLE);
		post.setId(postFocus.getPostId());
		Post post1 = this.postService.findPost(post, null);
		if(null == post1){
			throw new RuntimeException("该帖子ID不存在或者已被删除");
		}
		//判断贴子是否被这货赞过
		int flag = this.postFocusService.countPostFocus(postFocus);
		if(flag>0){
			throw new RuntimeException("该用户已经赞过这个贴子！");
		}

		this.postFocusService.insertPostFocus(postFocus);
		Integer focus = post1.getFocus();
		if(null == focus){
			focus = 0;
		}
		focus++;
		post.setFocus(focus);
		this.postService.modifyPostByPkSelective(post);
		//PostFocus tmp = new PostFocus();
		//tmp.setPostId(postFocus.getPostId());
		//int count = this.postFocusService.countPostFocus(tmp);
		String key = JUtil.getCacheKey(namespace,"postFocus",postFocus.getPostId());
		this.commonMemcached.delete(key);
		return focus;
	}

	
	@Override
	public JSONObject obtainAgreeList(int postId,Page page) throws Exception {
		String key = JUtil.getCacheKey(namespace,"postFocus",postId);
		List<Integer> userIds = this.commonMemcached.get(key);
		if(null == userIds || userIds.isEmpty()){
			//从数据库查询
			userIds = new ArrayList<Integer>();
			PostFocus tmp = new PostFocus();
			tmp.setPostId(postId);
			List<PostFocus> listPostFocus = this.postFocusService.listPostFocus(tmp, null, null, null);
			if(null!=listPostFocus && !listPostFocus.isEmpty()){
				for(PostFocus pf:listPostFocus){
					userIds.add(pf.getUid());
				}
				
				this.commonMemcached.set(key, CommonConstants.EXPIREDTIME, userIds);
			}
			
		}
		
		List<Integer> target  = userIds;int count = userIds.size();
		if(page!=null){
			//从缓存查
			int start = page.getBegin(),end = page.getEnd();
			if(start<0){
				start = 0;
			}
			
			if(end > count){
				end = count;
			}
			target =  userIds.subList(start, end);
		}
		
	
			
			List<GeneralUser> list = new ArrayList<GeneralUser>();
			for(Integer i:target){
				String ukey = JUtil.getCacheKey(namespace,"generalUser",i);
				GeneralUser cache = this.commonMemcached.get(ukey);
				if(null == cache){
					//查询
					GeneralUser tmp = new GeneralUser();
					tmp.setId(i);
					tmp.setEnabled(CommonConstants.ENABLE);
					tmp = this.generalUserService.findGeneralUser(tmp, null);
					if(null != tmp){
						list.add(tmp);
						this.commonMemcached.set(ukey, CommonConstants.CACHEEXPIREDTIME,tmp);
					}
				}else{
					list.add(cache);
				}
			}
			JSONObject json = new JSONObject();
			json.put("count",count);
			json.put("rows", list);
		
		return json;
	}



	@Override
	public GeneralUser weixinLogin(String openId, String token)
			throws Exception {

		UserWeixin uw = new UserWeixin();
		uw.setEnabled(CommonConstants.ENABLE);
		uw.setOpendId(openId);
		uw = this.userWeixinService.findUserWeixin(uw, null);
		if(null == uw){
			//微信注册

			JSONObject json = WeixinApi.invoke(token, openId);
			String nickname = json.getString("nickname");
			int sex = json.getIntValue("sex");
			final String city = json.getString("city");
			Integer cityCode = null;
			if(null!=city){
				City queryCity = this.cityService.findCity(new  City(), new MapperCallBackAdapter(){
					@Override
					public void doCriteria(Object obj) throws Exception {
						CityExample.Criteria c = (CityExample.Criteria) obj;
						c.andCityNameLike(city);
						c.andEnabledEqualTo(CommonConstants.ENABLE);
					}
				});
				if(null!=queryCity){
					cityCode = queryCity.getId();
				}
			}
			String headimgurl = json.getString("headimgurl");
			UserWeixin insertUser = new UserWeixin();
			insertUser.setAddTime(new Date().getTime());
			if(null!=cityCode){
				insertUser.setCity(cityCode);
			}
			insertUser.setOpendId(openId);
			insertUser.setNickName(nickname);
			insertUser.setHeadUrl(headimgurl);
			insertUser.setSex(sex);



			GeneralUser user = new GeneralUser();
			user.setEnabled(CommonConstants.ENABLE);
			user.setUserIcon(headimgurl);
			user.setNickName(nickname);
			user.setSex(sex);
			user.setTelphone((long)0);
			if(null!=cityCode){
				user.setCity(cityCode);
			}
			this.generalUserService.insertGeneralUser(user);
			insertUser.setUid(user.getId());
			this.userWeixinService.insertUserWeixin(insertUser);
			int userId = insertUser.getUid();
			user = new GeneralUser();
			user.setEnabled(CommonConstants.ENABLE);
			user.setId(userId);
			user = this.generalUserService.findGeneralUser(user, null);
			user.setUserIcon(headimgurl);
			return user;

		}
		//表示已经登陆
		int userId = uw.getUid();
		GeneralUser user = new GeneralUser();
		user.setEnabled(CommonConstants.ENABLE);
		user.setId(userId);
		user = this.generalUserService.findGeneralUser(user, null);
		if(null!=user){
			if(null == user.getImgName()){
				//没有自己上传附件 用微信自带
				user.setUserIcon(uw.getHeadUrl());
			}
			return user;
		}

		user = new GeneralUser();
		user.setEnabled(CommonConstants.ENABLE);
		user.setUserIcon(uw.getHeadUrl());
		user.setNickName(uw.getNickName());
		user.setSex(uw.getSex());
		user.setTelphone((long)0);
		if(null!=uw.getCity()){
			user.setCity(uw.getCity());
		}

		this.generalUserService.insertGeneralUser(user);
		int id = user.getId();
		new GeneralUser();
		user.setEnabled(CommonConstants.ENABLE);
		user.setId(id);
		user = this.generalUserService.findGeneralUser(user, null);
		user.setUserIcon(uw.getHeadUrl());
		uw.setUid(id);
		userWeixinService.modifyUserWeixinByPkSelective(uw);
		return user;

	}
}
